import {Types} from "mongoose"
import {GameActivityModel} from "../../database/models/gameActivity";
import {LipstickSeriesModel} from "../../database/models/lipstickSeries";
import {PlayerModel} from "../../database/models/player";
import {ProductModel} from "../../database/models/Product";
import {
  PressGroupModel,
  ProductGroupModel
} from "../../database/models/ProductGroup";
import {expect, requestToApiServer, setupTestEnv, tearDownTestEnv, TestEnv} from "./helper";

describe('减库存测试', () => {
  let env: TestEnv = null
  before(async () => {
    env = await setupTestEnv()
  })

  after(async () => {
    await tearDownTestEnv()
  })
  beforeEach(async () => {
    await ProductModel.updateMany({}, {$set: {state: 'off', stock: 0}})
    await LipstickSeriesModel.updateMany({}, {$set: {onStock: false}})
    await ProductGroupModel.updateMany({}, {$set: {state: 'off'}})
    await PressGroupModel.updateMany({}, {$set: {state: 'off'}})
  })

  context('全没库存', async () => {
    it('口红机系列 onStock === false 无法开始游戏', async () => {
      await requestToApiServer()
        .post(`/game/start/${env.lipstickSeries.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: false})
        })
    })
    it('口红机系列没货 product有货 无法开始游戏', async () => {
      const playerBefore = await PlayerModel.findOne({_id: env.player.id});
      await LipstickSeriesModel.updateMany({}, {$set: {onStock: false}})
      const lip = await LipstickSeriesModel.findById(env.lipstickSeries.id)
        .populate('products')
        .lean()
      await ProductModel.updateOne({_id: lip.products[0]._id}, {$set: {stock: 1, state: 'on'}})

      await requestToApiServer()
        .post(`/game/start/${env.lipstickSeries.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: false})
        })
      const playerAfter = await PlayerModel.findOne({_id: env.player.id});
      expect(playerAfter.coin).to.equal(playerBefore.coin)
    })

    it('扭蛋组 幸运盒子也无法开始游戏', async () => {
      const playerBefore = await PlayerModel.findOne({_id: env.player.id});

      await requestToApiServer()
        .post(`/game/luckBoxResult/${env.luckyGroup.id}`) // random objectId
        .set({'x-jwt': env.jwt})
        .send({draws: 1})
        .then(async res => {
          expect(res.body).have.properties({ok: false})
        })
      const playerAfter = await PlayerModel.findOne({_id: env.player.id});
      expect(playerAfter.gem).to.equal(playerBefore.gem)

    })

    it('按的准group onStock === off无法开始游戏', async () => {
      const playerBefore = await PlayerModel.findOne({_id: env.player.id});
      await requestToApiServer()
        .post(`/game/pressAccurateStart/${env.pressGroup.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: false})
        })
      const playerAfter = await PlayerModel.findOne({_id: env.player.id});
      expect(playerAfter.gem).to.equal(playerBefore.gem)
    })
    it('按的准没货 无法开始游戏', async () => {
      await PressGroupModel.updateMany({}, {$set: {state: 'on', stock: 0}})
      await LipstickSeriesModel.updateMany({}, {$set: {onStock: true, stock: 1}})
      await requestToApiServer()
        .post(`/game/pressAccurateStart/${env.pressGroup.id}`)
        .set({'x-jwt': env.jwt})
        .expect(200)
        .then(({body}) => {
          expect(body).to.have.properties({ok: false})
        })
    })
  })

  context('有少量库存', async () => {

    it('口红机系列还有一件商品 玩过后第二把没库存', async () => {
      await LipstickSeriesModel.updateMany({}, {$set: {onStock: true, stock: 1}})
      const lip = await LipstickSeriesModel.findById(env.lipstickSeries.id)
        .populate('products')
        .lean()
      await ProductModel.updateOne({_id: lip.products[0]._id}, {$set: {stock: 1, state: 'on'}})

      let act = null
      await requestToApiServer()
        .post(`/game/start/${env.lipstickSeries.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: true})
          act = body.data.activity
        })
      await GameActivityModel.updateOne({_id: act}, {
        $set: {
          canWin: true
        }
      })

      await requestToApiServer()
        .post(`/game/claim/${act}`)
        .set({'x-jwt': env.jwt})
        .expect(200)
        .send({win: true, stage: 2})
        .then(({body}) => {
          expect(body).to.have.properties({ok: true})
        })

      await ProductModel.updateOne({_id: lip.products[0]._id}, {$set: {stock: 0, state: 'on'}})

      await requestToApiServer()
        .post(`/game/start/${env.lipstickSeries.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: false})
        })
    })

    it('扭蛋组 幸运盒子有库存 但是不足', async () => {
      const playerBefore = await PlayerModel.findOne({_id: env.player.id});

      const pg = await ProductGroupModel.findByIdAndUpdate(env.luckyGroup,
        {$set: {state: 'on'}},
        {new: true})
        .populate('level1')
      await ProductModel.findByIdAndUpdate(pg.level1[0], {$set: {stock: 1, state: 'on'}})

      await requestToApiServer()
        .post(`/game/luckBoxResult/${env.luckyGroup.id}`) // random objectId
        .set({'x-jwt': env.jwt})
        .send({draws: 15})
        .then(async res => {
          expect(res.body).have.properties({ok: false})
        })
      const playerAfter = await PlayerModel.findOne({_id: env.player.id});
      expect(playerAfter.gem).to.equal(playerBefore.gem)

    })

    it('按的准还有刚好商品 玩过后第二把没库存 就不能再玩了', async () => {
      await PressGroupModel.updateMany({}, {$set: {state: 'on', stock: 1}})
      const press = await PressGroupModel.findByIdAndUpdate(env.pressGroup.id,
        {$set: {state: 'on'}}, {new: true})
        .populate(`level1`)
        .populate(`level2`)
        .populate(`level3`)
        .lean()

      const lip10 = await LipstickSeriesModel.findByIdAndUpdate(press.level1[0]._id,
        {$set: {onStock: true}}, {new: true})
        .populate('products')
        .lean()
      await ProductModel.updateOne({_id: lip10.products[0]._id}, {$set: {stock: 1, state: 'on'}})

      const lip20 = await LipstickSeriesModel.findByIdAndUpdate(press.level2[0]._id,
        {$set: {onStock: true}}, {new: true})
        .populate('products')
        .lean()
      await ProductModel.updateOne({_id: lip20.products[0]._id}, {$set: {stock: 1, state: 'on'}})

      const lip30 = await LipstickSeriesModel.findByIdAndUpdate(press.level3[0]._id,
        {$set: {onStock: true}}, {new: true})
        .populate('products')
        .lean()
      await ProductModel.updateOne({_id: lip30.products[0]._id}, {$set: {stock: 1, state: 'on'}})

      let act = null
      await requestToApiServer()
        .post(`/game/pressAccurateStart/${env.pressGroup.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: true})
          act = body.data.activity
        })
      await GameActivityModel.updateOne({_id: act}, {$set: {winLevel: 2}})

      await requestToApiServer()
        .post(`/game/pressAccurateClaim/${act}`)
        .set({'x-jwt': env.jwt})
        .expect(200)
        .send({winLevel: 2})
        .then(({body}) => {
          expect(body).to.have.properties({ok: true})
        })

      await requestToApiServer()
        .post(`/game/pressAccurateStart/${env.pressGroup.id}`)
        .set({'x-jwt': env.jwt})
        .then(({body}) => {
          expect(body).to.have.properties({ok: false})
        })
    })
  })

})
